package threading;


import java.util.concurrent.PriorityBlockingQueue;

//表示一个任务
class Mytask implements Comparable<Mytask>{
    //方便调用。就不用private修饰了
    public Runnable runnable;  //要完成的工作
    //为了方便后续的判定。使用绝对的时间戳，即是ms数和1970年相差的
    public long time;          //开始完成的时间

    //delay是一个3000ms的数字，多久后开始执行
    public Mytask(Runnable runnable, long delay) {
        this.runnable = runnable;
        //取当前的时间戳 + delay，
        this.time = System.currentTimeMillis() + delay;
    }

    //重写compareTo方法
    @Override
    public int compareTo(Mytask o) {
        //这样是每次去出的都是最小的时间戳
        return (int)(this.time - o.time);
    }
}


//模拟实现定时器的效果
class MyTimer{
    //带有优先级的堵塞队列，定时器中核心的数据结构
    //注意需要加上  比较规则
    PriorityBlockingQueue<Mytask> queue = new PriorityBlockingQueue<>();

    //创建一个锁对象  针对locker这个对象进行加锁，等待
    //public Object locker = new Object();

    public void schedule(Runnable runnable,long delay) {
        //根据参数，构造Mytask，插入队列即可
        Mytask mytask = new Mytask(runnable,delay);
        queue.put(mytask);
        synchronized(this) {
            this.notify();
        }
    }



    //在这里构造线程，负责具体的任务
    public MyTimer() {
        Thread t = new Thread(() -> {
            while (true) {
                try {
                    synchronized(this) {   //用this也可以 ， 用显式对象locker也行
                        Mytask mytask = queue.take();
                        long timeCurrent = System.currentTimeMillis();
                        if (mytask.time <= timeCurrent) {
                            //时间到了，可以执行任务
                            mytask.runnable.run();
                        } else {
                            //时间还未到，继续等待
                            //把刚才取出来的，继续放到队列中去
                            queue.put(mytask);
                            //加入wait等待
                            this.wait(mytask.time - timeCurrent );  //针对locker这个对象进行加锁，等待
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        //启动线程
        t.start();
    }
}


public class ThreadDemo23Timer {
    public static void main(String[] args) {

        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello4");
            }
        }, 4000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello3");
            }
        }, 3000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello2");
            }
        }, 2000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello1");
            }
        }, 1000);

        System.out.println("hello0");
    }
}
